#!/usr/bin/php -q
<?PHP
/* Copyright 2005-2023, Lime Technology
 * Copyright 2012-2023, Bergware International.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version 2,
 * as published by the Free Software Foundation.
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 */
?>
<?
$docroot = '/usr/local/emhttp';
$varroot = '/var/local/emhttp';
$md5_old = -1;

require_once "$docroot/webGui/include/Helpers.php";
require_once "$docroot/webGui/include/publish.php";
extract(parse_plugin_cfg('dynamix',true));

// add translations
$_SERVER['REQUEST_URI'] = 'dashboard';
$login_locale = _var($display,'locale');
require_once "$docroot/webGui/include/Translations.php";

// remember current language
$locale_init = $locale;

/* Parse the ini files */
$shares = parse_ini_file('state/shares.ini', true);
$disks = parse_ini_file('state/disks.ini', true);

function update_translation($locale) {
  global $docroot,$language;
  $language = [];
  if ($locale) {
    $text = "$docroot/languages/$locale/translations.txt";
    if (file_exists($text)) {
      $store = "$docroot/languages/$locale/translations.dot";
      if (!file_exists($store)) file_put_contents($store,serialize(parse_lang_file($text)));
      $language = unserialize(file_get_contents($store));
    }
    $text = "$docroot/languages/$locale/dashboard.txt";
    if (file_exists($text)) {
      $store = "$docroot/languages/$locale/dashboard.dot";
      if (!file_exists($store)) file_put_contents($store,serialize(parse_lang_file($text)));
      $language = array_merge($language,unserialize(file_get_contents($store)));
    }
  }
}

while (true) {
  extract(parse_plugin_cfg('dynamix',true));
  if (_var($display,'locale') != $locale_init) {
    $locale_init = _var($display,'locale');
    update_translation($locale_init);
  }
  unset($memory,$df,$fans,$lsof);
  exec("awk '/^Mem(Total|Available)/{print $2*1024}' /proc/meminfo",$memory);
  exec("df --output=pcent,used /boot /var/log /var/lib/docker 2>/dev/null|awk '(NR>1){print $1,$2*1024}'",$df);
  exec("sensors -uA 2>/dev/null|grep -Po 'fan\d_input: \K\d+'",$fans);
  [$total,$free] = $memory;
  $used  = $total-$free;
  $names = [_('System'),_('Free')];
  $bytes = $echo = [];
  $hooks = array_filter(glob("/usr/local/emhttp/plugins/*/system/*",GLOB_NOSORT),function($file){return is_executable($file);});
  foreach ($hooks as $hook) {
    $data = @intval(exec(escapeshellarg($hook)));
    if (!$data || $data>$used) continue;
    $names[] = _(str_replace('_',' ',basename($hook))); // name of element
    $bytes[] = $data;                                   // value in bytes
  }
  // parse RAM graph
  $a = 'ram';
  $services  = $used-array_sum($bytes);
  $echo[$a][] = round(100*$used/$total)."%";
  $echo[$a][] = my_scale($used,$unit,null,-1,1024)." $unit";
  $echo[$a][] = round(100*$free/$total);
  $echo[$a][] = my_scale($free,$unit,null,-1,1024)." $unit";
  $echo[$a][] = round(100*$services/$total);
  $echo[$a][] = my_scale($services,$unit,null,-1,1024)." $unit";
  foreach ($bytes as $byte) {
    // parse hook script information for RAM usage graph
    $echo[$a][] = round(100*$byte/$total);
    $echo[$a][] = my_scale($byte,$unit,null,-1,1024)." $unit";
  }
  // add element names
  $echo['name'] = $names;
  // parse the graphs for flash, log & docker
  foreach ($df as $data) {
    [$pcent,$used] = explode(' ',$data);
    $echo['sys'][] = [$pcent,my_scale($used,$unit,null,-1,1024)." $unit"];
  }
  // add fans information
  if (count($fans)) $echo['fan'] = array_map(function($fan){return "$fan RPM";},$fans);

  // add streams information
  /* Extract keys from both ini files */
  $paths = array_keys($disks);

  /* Validate and filter accessible mount points */
  $valid_paths = array_filter($paths, function($key) {
    $mnt_path = '/mnt/' . $key;
    /* Check if the directory exists and is a valid mount point */
    return is_dir($mnt_path) && trim((shell_exec("mountpoint -q " . escapeshellarg($mnt_path) . " && echo 1")) ?? '') === '1';
  });

  /* Construct the list of paths */
  $mnt_paths = array_map(function($key) {
    return '/mnt/'.escapeshellarg($key);
  }, $valid_paths);

  /* Combine paths into the command */
  $mnt_list = implode(' ', $mnt_paths);

  /* Build and execute the modified command */
  $command = 'LANG="en_US.UTF8" timeout 3 lsof -Fn '.$mnt_list.' 2>/dev/null | awk -F/ \'$1=="n" && $2=="mnt" && $5!="" {print $4"/"$5"/"$6"/"$7}\' | sort -u | awk -F/ \'{print $1}\'';
  exec($command, $lsof);

  $share = array_keys($shares);
  $count = array_count_values($lsof ?? array());
  foreach ($share as $name) $echo['stream'][] = $count[$name]??0;
  $echo = json_encode($echo);
  $md5_new = md5($echo,true);
  if ($md5_new !== $md5_old) {
    $md5_old = publish('update1',$echo)!==false ? $md5_new : -1;
  }
  sleep(5);
}
?>
